package com.hadwinling.alogriithm.projectforpso.miemiepso

import scala.util.Random

object PSOStuff {
  //  (num,(pos,vel,pb_pos))
  def addFitness(particle:Iterator[(Int, (Array[Double], Array[Double], Array[Double]))]) ={
    particle.map{
      x =>
        val fitness=Function.linkPrediction(x._2._1)
        val pb_fitness=Function.linkPrediction(x._2._3)
        //  (num,(pos,vel,fitness,pb_pos,pb_fitness))
        (x._1,(x._2._1,x._2._2,fitness,x._2._3,pb_fitness))
    }
  }
  def updateParticle(num:Int,pos:Array[Double],vel:Array[Double],pb_pos:Array[Double],gb_pos:Array[Double])={
    val newpos:Array[Double]=Array.fill(SparkPSO.dim)(0.0)
    val newvel: Array[Double] = Array.fill(SparkPSO.dim)(0.0)
    val newpb_pos: Array[Double] = Array.fill(SparkPSO.dim)(0.0)
    val fitness:Double=Function.linkPrediction(pos)
    var newfitness:Double=0.0
    List.range(0,SparkPSO.dim).foreach{ i=>
      val c1=1// c1 and c2  are Acceleration Factors
    val c2=1
      val w=1 //w is weight
      /*   Apply the formula to update imformation of  the particle in PSO */
      newvel(i)=w*vel(i)+c1*Random.nextDouble()*(pb_pos(i)-pos(i))+c2*Random.nextDouble()*(gb_pos(i)-pos(i))
      newpos(i)=pos(i)+newvel(i)
    }
    newfitness=Function.linkPrediction(newpos)
    /*    if new fitness is better than the old one ,update the gb_pos of the particle*/
    if(newfitness<fitness){
      List.range(0,SparkPSO.dim).foreach{i=>
        newpb_pos(i)=newpos(i)
      }
    }else{
      List.range(0,SparkPSO.dim).foreach{i=>
        newpb_pos(i)=pb_pos(i)
      }
    }
    (num,(newpos,newvel,newpb_pos))
  }
}

